package com.mxnet.chongjin.supoman.activity;

import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.text.method.PasswordTransformationMethod;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.espressif.iot.esptouch.EsptouchTask;
import com.espressif.iot.esptouch.IEsptouchListener;
import com.espressif.iot.esptouch.IEsptouchResult;
import com.espressif.iot.esptouch.IEsptouchTask;
import com.espressif.iot.esptouch.task.__IEsptouchTask;
import com.espressif.iot.esptouch.util.ByteUtil;
import com.espressif.iot.esptouch.util.EspAES;
import com.espressif.iot.esptouch.util.EspNetUtil;
import com.mxnet.chongjin.supoman.MainActivity;
import com.mxnet.chongjin.supoman.R;
import com.mxnet.chongjin.supoman.utils.EspUtils;

import java.lang.ref.WeakReference;
import java.net.NetworkInterface;
import java.util.List;

public class NetConfigActivity extends AppCompatActivity implements View.OnClickListener {
    private Context mContext;
    private Button mButton;
    private LinearLayout mLinearLayout;
    private WifiManager mWifiManager;
    private WifiInfo mWifiInfo;
    private TextView mTextView;
    private EditText mEditText;
    private SharedPreferences mPreferences;
    private SharedPreferences.Editor mEditor;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_net_config);
        getWindow().getDecorView().setSystemUiVisibility(
                View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
        getWindow().setStatusBarColor(Color.TRANSPARENT);

        mContext = NetConfigActivity.this;
        mPreferences = getSharedPreferences("supoman", MODE_PRIVATE);
        mEditor = mPreferences.edit();

        IntentFilter filter = new IntentFilter(WifiManager.NETWORK_STATE_CHANGED_ACTION);
        registerReceiver(mReceiver, filter);
        initData();
        initView();
    }

    public void initData() {
        mWifiManager = (WifiManager) mContext.getSystemService(WIFI_SERVICE);
        if (ContextCompat.checkSelfPermission(mContext, Manifest.permission_group.LOCATION) != PackageManager.PERMISSION_GRANTED) {
            // 获取wifi连接需要定位权限,没有获取权限
            ActivityCompat.requestPermissions(NetConfigActivity.this, new String[]{
                    Manifest.permission.ACCESS_FINE_LOCATION,
                    Manifest.permission.ACCESS_COARSE_LOCATION,
                    Manifest.permission.ACCESS_WIFI_STATE
            }, 1);
        }
        mWifiInfo = mWifiManager.getConnectionInfo();
        mWifiInfo.getSupplicantState();

    }

    public void initView() {
        mButton = findViewById(R.id.btn_net_config);
        mButton.setEnabled(false);
        mButton.setOnClickListener(this);

        mLinearLayout = findViewById(R.id.ll_net_config);
        mLinearLayout.setOnClickListener(this);

        mTextView = findViewById(R.id.tv_net_config_wifi_name);
        String s = mWifiInfo.getSSID() == null ? getResources().getString(R.string.no_wifi) : mWifiInfo.getSSID();
        mTextView.setText(s);
        mEditText = findViewById(R.id.et_net_config_wifi_pwd);
        mEditText.setTransformationMethod(PasswordTransformationMethod.getInstance());

    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_net_config:
                boolean isMatched = mPreferences.getBoolean("isMatched", false);
                //boolean isMatched = true;
                if (isMatched) {
                    Intent intent = new Intent();
                    intent.setClass(mContext, ConfigGuideActivity.class);
                    startActivity(intent);
                    finish();
                } else {
                    if ((Boolean) mButton.getTag()) {
                        Toast.makeText(this, R.string.wifi_5g_message, Toast.LENGTH_SHORT).show();
                        return;
                    }

                    byte[] ssid = mTextView.getTag() == null ? ByteUtil.getBytesByString(mTextView.getText().toString())
                            : (byte[]) mTextView.getTag();
                    byte[] password = ByteUtil.getBytesByString(mEditText.getText().toString());
                    byte[] bssid = EspNetUtil.parseBssid2bytes(mWifiInfo.getBSSID());
                    byte[] deviceCount = "1".getBytes();

                    if (mTask != null) {
                        mTask.cancelEsptouch();
                    }
                    mTask = new EsptouchAsyncTask4(this,mTextView,mEditText);
                    mTask.execute(ssid, bssid, password, deviceCount);
                }
                break;
            case R.id.ll_net_config:
                //
                Intent intent = new Intent();
                intent.setClass(mContext, MainActivity.class);
                startActivity(intent);
                finish();
                break;
        }
    }

    private static final String TAG = "NetConfigActivity";

    private static final boolean AES_ENABLE = false;
    private static final String AES_SECRET_KEY = "1234567890123456"; // TODO modify your own key


    private IEsptouchListener myListener = new IEsptouchListener() {

        @Override
        public void onEsptouchResultAdded(final IEsptouchResult result) {
            onEsptoucResultAddedPerform(result);
        }
    };

    private EsptouchAsyncTask4 mTask;

    private BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (action == null) {
                return;
            }

            switch (action) {
                case WifiManager.NETWORK_STATE_CHANGED_ACTION:
                    WifiInfo wifiInfo = intent.getParcelableExtra(WifiManager.EXTRA_WIFI_INFO);
                    onWifiChanged(wifiInfo);
                    break;
            }
        }
    };

    @Override
    protected void onDestroy() {
        super.onDestroy();

        unregisterReceiver(mReceiver);
    }

    private void onWifiChanged(WifiInfo info) {
        if (info == null) {
            mTextView.setText("");
            mTextView.setTag(null);
            mButton.setEnabled(false);
            mButton.setTag(null);
            if (mTask != null) {
                mTask.cancelEsptouch();
                mTask = null;
                new AlertDialog.Builder(mContext)
                        .setMessage("Wifi disconnected or changed")
                        .setNegativeButton(android.R.string.cancel, null)
                        .show();
            }
        } else {
            String ssid = info.getSSID();
            if (ssid.startsWith("\"") && ssid.endsWith("\"")) {
                ssid = ssid.substring(1, ssid.length() - 1);
            }
            mTextView.setText(ssid);

            if(mPreferences.contains("supoman_"+ssid ))
            {
                mEditText.setText(mPreferences.getString("supoman_"+ssid ,""));
            }


            mTextView.setTag(ByteUtil.getBytesByString(ssid));
            byte[] ssidOriginalData = EspUtils.getOriginalSsidBytes(info);
            mTextView.setTag(ssidOriginalData);

            String bssid = info.getBSSID();

            mButton.setEnabled(true);
            mButton.setTag(Boolean.FALSE);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                int frequence = info.getFrequency();
                if (frequence > 4900 && frequence < 5900) {
                    // Connected 5G wifi. Device does not support 5G
                    mButton.setTag(Boolean.TRUE);
                }
            }
        }
    }

    private void onEsptoucResultAddedPerform(final IEsptouchResult result) {
        runOnUiThread(new Runnable() {

            @Override
            public void run() {
                String text = result.getBssid() + " is connected to the wifi";
                Toast.makeText(mContext, text,
                        Toast.LENGTH_LONG).show();
            }

        });
    }

    private static class EsptouchAsyncTask4 extends AsyncTask<byte[], Void, List<IEsptouchResult>> {
        private WeakReference<NetConfigActivity> mActivity;

        // without the lock, if the user tap confirm and cancel quickly enough,
        // the bug will arise. the reason is follows:
        // 0. task is starting created, but not finished
        // 1. the task is cancel for the task hasn't been created, it do nothing
        // 2. task is created
        // 3. Oops, the task should be cancelled, but it is running
        private final Object mLock = new Object();
        private ProgressDialog mProgressDialog;
        private AlertDialog mResultDialog;
        private IEsptouchTask mEsptouchTask;
        //private String wifiName,password;
        private TextView textViewName;
        private EditText editTextPassword;

        EsptouchAsyncTask4(NetConfigActivity activity,TextView tvName,EditText etPassword) {
            mActivity = new WeakReference<>(activity);
            this.textViewName=tvName;
            this.editTextPassword=etPassword;
        }

        void cancelEsptouch() {
            cancel(true);
            if (mProgressDialog != null) {
                mProgressDialog.dismiss();
            }
            if (mResultDialog != null) {
                mResultDialog.dismiss();
            }
            if (mEsptouchTask != null) {
                mEsptouchTask.interrupt();
            }
        }

        @Override
        protected void onPreExecute() {
            Activity activity = mActivity.get();
            mProgressDialog = new ProgressDialog(activity);
            mProgressDialog.setMessage("Esptouch is configuring, please wait for a moment...");
            mProgressDialog.setCanceledOnTouchOutside(false);
            mProgressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
                @Override
                public void onCancel(DialogInterface dialog) {
                    synchronized (mLock) {
                        if (__IEsptouchTask.DEBUG) {
                            Log.i(TAG, "progress dialog back pressed canceled");
                        }
                        if (mEsptouchTask != null) {
                            mEsptouchTask.interrupt();
                        }
                    }
                }
            });
            mProgressDialog.setButton(DialogInterface.BUTTON_NEGATIVE, activity.getText(android.R.string.cancel),
                    new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            synchronized (mLock) {
                                if (__IEsptouchTask.DEBUG) {
                                    Log.i(TAG, "progress dialog cancel button canceled");
                                }
                                if (mEsptouchTask != null) {
                                    mEsptouchTask.interrupt();
                                }
                            }
                        }
                    });
            mProgressDialog.show();
        }

        @Override
        protected List<IEsptouchResult> doInBackground(byte[]... params) {
            NetConfigActivity activity = mActivity.get();
            int taskResultCount;
            synchronized (mLock) {
                // !!!NOTICE
                byte[] apSsid = params[0];
                byte[] apBssid = params[1];
                byte[] apPassword = params[2];
                byte[] deviceCountData = params[3];
                taskResultCount = deviceCountData.length == 0 ? -1 : Integer.parseInt(new String(deviceCountData));
                Context context = activity.getApplicationContext();
                if (AES_ENABLE) {
                    byte[] secretKey = AES_SECRET_KEY.getBytes();
                    EspAES aes = new EspAES(secretKey);
                    mEsptouchTask = new EsptouchTask(apSsid, apBssid, apPassword, aes, context);
                } else {
                    mEsptouchTask = new EsptouchTask(apSsid, apBssid, apPassword, null, context);
                }
                mEsptouchTask.setEsptouchListener(activity.myListener);
            }
            return mEsptouchTask.executeForResults(taskResultCount);
        }

        @Override
        protected void onPostExecute(final List<IEsptouchResult> result) {
            final NetConfigActivity activity = mActivity.get();
            mProgressDialog.dismiss();
            mResultDialog = new AlertDialog.Builder(activity)
                    .setIcon(R.mipmap.mine_head_1)
                    .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            if (result == null) {
                                mResultDialog.dismiss();
                            } else if (result.get(0).isSuc()) {
                                SharedPreferences sp = activity.getSharedPreferences("supoman", MODE_PRIVATE);
                                SharedPreferences.Editor editor = sp.edit();
                                editor.putBoolean("isMatched", true);
                                editor.putString("supoman_"+textViewName.getText(),editTextPassword.getText().toString());
                                editor.commit();
                                Intent intent = new Intent();
                                intent.setClass(activity, ConfigGuideActivity.class);
                                activity.startActivity(intent);
                                activity.finish();
                            }
                        }
                    })
                    .create();
            mResultDialog.setCanceledOnTouchOutside(false);
            if (result == null) {
                mResultDialog.setMessage("Connect failed");
                mResultDialog.show();
                return;
            }

            IEsptouchResult firstResult = result.get(0);
            // check whether the task is cancelled and no results received
            if (!firstResult.isCancelled()) {
                int count = 0;
                // max results to be displayed, if it is more than maxDisplayCount,
                // just show the count of redundant ones
                final int maxDisplayCount = 5;
                // the task received some results including cancelled while
                // executing before receiving enough results
                if (firstResult.isSuc()) {
                    StringBuilder sb = new StringBuilder();
                    for (IEsptouchResult resultInList : result) {
                        activity.mEditor.putString("machineip", resultInList.getInetAddress().getHostAddress());
                        activity.mEditor.commit();
                        String mac = "";
                        try {
                            byte[] b = NetworkInterface.getByInetAddress(resultInList.getInetAddress()).getHardwareAddress();
                            StringBuffer buffer = new StringBuffer();
                            for (int i = 0; i < b.length; i++) {
                                if (i != 0) {
                                    buffer.append(':');
                                }
                                String str = Integer.toHexString(b[i] & 0xFF);
                                buffer.append(str.length() == 1 ? 0 + str : str);
                            }
                            mac = buffer.toString().toUpperCase();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        sb.append("Connect success");
                        count++;
                        if (count >= maxDisplayCount) {
                            break;
                        }
                    }
                    if (count < result.size()) {
                        sb.append("\nthere's ")
                                .append(result.size() - count)
                                .append(" more result(s) without showing\n");
                    }
                    mResultDialog.setMessage(sb.toString());
                } else {
                    mResultDialog.setMessage("Connect failed");
                }
                mResultDialog.show();
            }

            activity.mTask = null;
        }
    }
}
